/**
 * Copyright (c) [2025] [何屹林]
 *
 * 保留所有权利。
 *
 * 文件名称：TreeGraph.h
 * 模块功能说明：
 * 该模块实现了树形图的生成，定义可视化AST生成树形图的各种函数，绘制树形图。
 *
 * 华南师范大学-计算机学院-网络工程-1班
 * 作者：何屹林-20222132023
 * 完成日期：2025年7月24日
 */
#ifndef TREEGRAPH_H
#define TREEGRAPH_H

#include <QGraphicsScene>
#include <QGraphicsRectItem>
#include <QGraphicsTextItem>
#include <QGraphicsLineItem>
#include <QGraphicsDropShadowEffect>

#include "utils.h"

class ASTGraphicsScene : public QGraphicsScene {
public:
    explicit ASTGraphicsScene(SyntaxTree tree, QObject* parent = nullptr, qreal maxWidth = 750.0)
        : QGraphicsScene(parent), root(tree), m_maxWidth(maxWidth) {
        layoutTree();
    }

private:
    SyntaxTree root;
    QMap<SyntaxNode*, QGraphicsItem*> nodeItems;
    QMap<SyntaxNode*, qreal> subtreeOffsets;
    qreal m_maxWidth;

    struct LayoutConfig {
        qreal hSpacing = 40.0;   // 水平间距
        qreal vSpacing = 80.0;   // 垂直间距
        qreal hPadding = 10.0;   // 水平内边距
        qreal vPadding = 8.0;    // 垂直内边距
        qreal minWidth = 60.0;   // 节点最小宽度
        qreal minHeight = 35.0;  // 节点最小高度
        qreal fontSize = 10.0;   // 字体大小
    } config;

    void layoutTree() {
        clear();
        nodeItems.clear();
        if (!root) return;

        createNodeItems(root);//对树建立每个结点的可视图

        QRectF treeRect = calculateLayout(root, 0, 0);

//        centerTree(root, 0);
    }

    void createNodeItems(SyntaxNode* node)//深度优先建树
    {
        if (!node || nodeItems.contains(node)) return;

        QGraphicsRectItem* nodeItem = createStyledNode(node->nodeStr);
        addItem(nodeItem);
        nodeItems[node] = nodeItem;

        for (SyntaxNode* child : node->children) {
            createNodeItems(child);
        }
    }

    QGraphicsRectItem* createStyledNode(const QString& text) {
        QGraphicsTextItem* textItem = new QGraphicsTextItem(text);
        textItem->setFont(QFont("Consolas", config.fontSize));
        QRectF textRect = textItem->boundingRect();
        delete textItem;

        qreal width = qMax(textRect.width() + 2 * config.hPadding, config.minWidth);
        qreal height = qMax(textRect.height() + 2 * config.vPadding, config.minHeight);

        QGraphicsRectItem* rectItem = new QGraphicsRectItem(0, 0, width, height);
        rectItem->setBrush(QColor(240, 248, 255));
        rectItem->setPen(QPen(QColor(100, 150, 200), 1.0));
        rectItem->setFlag(QGraphicsItem::ItemIsMovable, true); // 允许手动调整

        QGraphicsTextItem* actualTextItem = new QGraphicsTextItem(text, rectItem);
        actualTextItem->setFont(QFont("Consolas", config.fontSize));
        actualTextItem->setDefaultTextColor(Qt::darkBlue);
        actualTextItem->setPos(
            (width - actualTextItem->boundingRect().width()) / 2,
            (height - actualTextItem->boundingRect().height()) / 2
            );//居中

        return rectItem;
    }


    QRectF calculateLayout(SyntaxNode* node, qreal x, qreal y) {
        if (!node || !nodeItems.contains(node)) return QRectF();

        QGraphicsItem* item = nodeItems[node];
        qreal nodeWidth = item->boundingRect().width();
        qreal nodeHeight = item->boundingRect().height();

        item->setPos(x - nodeWidth/2, y);

        if (node->children.empty()) {
            return QRectF(x - nodeWidth/2, y, nodeWidth, nodeHeight);
        }

        qreal totalChildWidth = 0;
        qreal maxChildHeight = 0;
        QList<QRectF> childRects;

        qreal childY = y + nodeHeight + config.vSpacing;
        qreal childX = x ; // 从当前结点开始向下

        for (SyntaxNode* child : node->children) {
            QRectF childRect = calculateLayout(child, childX, childY);

            qreal childWidth = childRect.width();
            qreal childHeight = childRect.height();

            childRects.append(childRect);
            totalChildWidth += childWidth;
            maxChildHeight = qMax(maxChildHeight, childHeight);

            // 更新下一个子节点的起始X位置
            childX = childRect.right() + config.hSpacing;

            // 添加连接线
            addConnection(item, nodeItems[child]);
        }


        qreal startX = x;
        qreal currentX = startX;

        for (int i = 0; i < node->children.size(); i++) {
            SyntaxNode* child = node->children[i];
            QGraphicsItem* childItem = nodeItems[child];
            QRectF childRect = childRects[i];

//            // 计算新的居中位置
//            qreal newX = currentX + childRect.width()/2;
//            childItem->setPos(newX - childItem->boundingRect().width()/2, childRect.y());

            // 更新连接线
            updateConnection(item, childItem);

            currentX += childRect.width() + config.hSpacing;
        }

        // 返回当前子树边界
        qreal subtreeWidth = qMax(nodeWidth, totalChildWidth + config.hSpacing * (node->children.size() - 1));
        qreal subtreeHeight = nodeHeight + config.vSpacing + maxChildHeight;

        return QRectF(x, y, subtreeWidth, subtreeHeight);
    }

    void addConnection(QGraphicsItem* parent, QGraphicsItem* child) {
        QLineF line(
            parent->boundingRect().center().x(),
            parent->boundingRect().bottom(),
            child->boundingRect().center().x(),
            child->boundingRect().top()
            );

        QGraphicsLineItem* lineItem = new QGraphicsLineItem(line);
        lineItem->setPen(QPen(QColor(120, 120, 160), 1.0));
        lineItem->setZValue(-1);
        lineItem->setData(0, QVariant::fromValue(parent)); // 存储父节点引用
        lineItem->setData(1, QVariant::fromValue(child)); // 存储子节点引用
        addItem(lineItem);
    }

    void updateConnection(QGraphicsItem* parent, QGraphicsItem* child) {
        // 查找并更新连接线
        for (QGraphicsItem* item : items()) {
            if (QGraphicsLineItem* line = dynamic_cast<QGraphicsLineItem*>(item)) {
                if (line->data(0).value<QGraphicsItem*>() == parent &&
                    line->data(1).value<QGraphicsItem*>() == child) {

                    QLineF newLine(
                        parent->sceneBoundingRect().center().x(),
                        parent->sceneBoundingRect().bottom(),
                        child->sceneBoundingRect().center().x(),
                        child->sceneBoundingRect().top()
                        );
                    line->setLine(newLine);
                    break;
                }
            }
        }
    }

//    void centerTree(SyntaxNode* node, qreal centerX) {
//        if (!node || !nodeItems.contains(node)) return;

//        // 计算当前节点中心
//        QGraphicsItem* item = nodeItems[node];
//        QRectF nodeRect = item->sceneBoundingRect();
//        qreal currentCenter = nodeRect.left() + nodeRect.width() / 2;

//        // 计算偏移量
//        qreal offset = centerX - currentCenter;

//        // 存储偏移量（用于递归移动子树）
//        subtreeOffsets[node] = offset;

//        // 递归处理子节点
//        for (SyntaxNode* child : node->children) {
//            centerTree(child, centerX);
//        }

//        // 移动当前节点及其所有子节点
//        moveSubtree(node, offset);
//    }

//    void moveSubtree(SyntaxNode* node, qreal offsetX) {
//        if (!node || !nodeItems.contains(node)) return;

//        // 移动当前节点
//        QGraphicsItem* item = nodeItems[node];
//        item->setPos(item->pos().x() + offsetX, item->pos().y());

//        // 更新连接线位置
//        for (SyntaxNode* child : node->children) {
//            if (nodeItems.contains(child)) {
//                updateConnection(item, nodeItems[child]);
//            }
//        }

//        // 递归移动所有子节点
//        for (SyntaxNode* child : node->children) {
//            moveSubtree(child, offsetX);
//        }
//    }
};

#endif // TREEGRAPH_H
